﻿// See https://aka.ms/new-console-template for more information
//代理模式
//当用户无法直接访问某个对象或者访问某个对象存在困难时，可以通过一个代理对象来间接访问。代理模式允许我们在访问对象时添加额外的行为，而不需要更改对象本身。
//在代理模式中，代理和实际对象实现相同的接口，这样客户端就可以通过代理来访问实际对象，保证客户端使用的透明性。代理可以在访问实际对象之前或之后执行一些操作，例如验证客户端的请求，缓存结果，记录日志等。
//在软件开发中，由于某些原因，我们不想或不能直接访问一个对象，此时我们可以通过一个被称为i而代理的第三者来实现间接访问，这就是代理模式。

//代理模式分为以下几个对象：
//·Subject（抽象主题角色）：他声明了真实主题角色和代理主题角色的共同接口，这样客户端只需要根据抽象主题接口进行编程即可。
//·Proxy（代理主题角色）：代理主题角色包含一个对于真实主题角色的引用的维护，当客户端要调用一些方法时，代理主题角色将会调用真实主题角色中的同名方法。当然代理主题角色是可以添加额外操作的。例如在保护代理中，代理角色就需要对访问真实主题的请求做甄别。
//·ConcreteSubject（真实主题角色）：他定义了代理角色所代表的真实对象，在真实对象中实现了真实的业务操作，客户端通过代理角色间接调用真实角色中的业务逻辑。

//直接访问实际对象
IConnection realConnection=new RealConnection("10.0.0.1","user","password");
realConnection.Connect();
realConnection.Disconnect();

Console.WriteLine("---------------------------------------");

//访问代理对象
IConnection vpnConnectionProxy=new VpnConnectionProxy("10.0.0.1", "user", "password");
vpnConnectionProxy.Connect();
vpnConnectionProxy.Disconnect();

//接口，定义了对象的行为
public interface IConnection
{
    void Connect();

    void Disconnect();
}

//实际对象，实现了接口
public class RealConnection : IConnection
{
    private string ServerAddress;
    private string UserName;
    private string Password;

    public RealConnection(string serverAddress, string userName, string password)
    {
        ServerAddress = serverAddress;
        UserName = userName;
        Password = password;
    }

    public void Connect()
    {
        Console.WriteLine($"Connecting to server at {ServerAddress}...");
        Console.WriteLine($"Logging in with UserName={UserName} and Password={Password}");
        Console.WriteLine("Connecting established.");
    }

    public void Disconnect()
    {
        Console.WriteLine("Disconnecting from server");
    }
}

//代理类,实现了接口并维护了一个实际对象的引用，用梯子做代理
public class VpnConnectionProxy : IConnection
{
    private RealConnection _realConnection;

    public VpnConnectionProxy(string serverAddress, string username, string password)
    {
        _realConnection = new RealConnection(serverAddress, username, password);
    }

    //实现了接口方法，并在访问之前执行一些操作
    public void Connect()
    {
        Console.WriteLine("Initiating VPN connection....");
        Console.WriteLine("Performing security checks....");
        Console.WriteLine("Authenticating user....");

        //访问实际对象
        _realConnection.Connect();

        Console.WriteLine("VPN connection established.");
    }

    //实现了接口方法，并在访问实际对象之后执行一些操作
    public void Disconnect()
    {
        Console.WriteLine("Terminating VPN connection....");
        //访问实际对象
        _realConnection.Disconnect();
        Console.WriteLine("VPN connection terminated");
    }
}